home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…stman Always Clicks Twice / ADC Developer CD (1993-01) (''The Postman Always Clicks Twice'')_iso / Dev.CD 199301.iso / Technical Documentation / Sample Code / Snippets / Platforms & Tools / Recipes.C++ 1.0a4 < prev   
Encoding:
Text File  |  1992-11-16  |  29.8 KB  |  1,782 lines  |  [TEXT/MPS ]

  1. #############################################################################
  2. Recipes for MPW C++      1.0a4
  3. Kent Sandvik DTS        15 September 1991
  4.  
  5. Permission to republish this is granted, as long as the contents
  6. are not modified/altered/shortened in any way without consulting the author first.
  7.  
  8. Place in MPW Folder, and put following line (example) in UserStartup:
  9.     AddMenu    Special 'C++ Recipes/1'    'Open "{MPW}Recipes.C++"'
  10.                                  ^ triggered from option-1
  11.  
  12. Please redirect any comments, bug reports and such to:
  13. ksand@apple.com (Usenet, Internet)
  14. KSAND           (AppleLink)
  15. 75300, 1331     (CompuServe)
  16.  
  17. References:
  18.     C++ Programming Language (second edition), Bjarne Stroustrup
  19.     Annotated C++ Reference Manual, Ellis & Stroustrup
  20.     All kinds of private notes/hacks (Usenet comp.lang.c++, CompuServe)
  21.  
  22. Future plans:
  23.     * more material, bug fixes, better explanations
  24.     * 411 (template/lookup support), or something more hypertext:ish
  25.     
  26. Thanks!
  27.     Johan Strandberg, Common Knowledge
  28.     
  29. #############################################################################
  30.  
  31. // C+ class test template
  32.  
  33. #include <stream.h>
  34.  
  35. class TFoo {
  36. public:
  37.     TFoo();            // constructor
  38.     ~TFoo();        // destructor
  39.     
  40. protected:
  41.     long    fField;    
  42. private:
  43. };
  44.  
  45.  
  46. // Method implementations
  47.  
  48. TFoo::TFoo()        // constructor
  49. {
  50.     cout << "inside TFoo constructor\n";
  51. }
  52.  
  53. TFoo::~TFoo()        // destructor
  54. {
  55. // empty for the moment
  56. }
  57.  
  58.  
  59. class TBar : public TFoo{
  60. public:
  61.         TBar() { cout << "inside TBar constructor\n";}
  62.     virtual void Member();
  63. };
  64.  
  65. void TBar::Member()
  66. {
  67.     cout << "inside TBar::Member\n";
  68. }
  69.  
  70.  
  71. TBar    *aBar;
  72.  
  73. main()
  74. {
  75.     aBar = new TBar;
  76.     return 0;
  77. }
  78.  
  79.  
  80. // volatile macro
  81.  
  82. #define VOLATILE(a) ((void) &a)
  83.  
  84.  
  85. // global scope operator
  86.  
  87. int x;
  88.  
  89. void func()
  90. {
  91.     int x = 1;        // use local x
  92.     ::x   = 2;      // use global x
  93. }
  94.  
  95.  
  96. // void pointers - can be made to point at anything
  97.  
  98. void* malloc(unsigned size);  // C style memory allocation
  99. void  free(void*);
  100.  
  101. void func()
  102. {
  103.     int* pi  = (int *)malloc(10*sizeof(int));
  104.     char* pc = (char *)malloc(10);
  105.     // ...
  106.     free(pi);
  107.     free(pc);
  108. }
  109.  
  110.  
  111. // pointers
  112.  
  113. int* pi;                    // pointer to int
  114. char** cpp;                    // pointer to array to char
  115. int (*vp)[10];                // pointer to array of 10 ints
  116. int (*fp) (char, char*);    // pointer to function taking 
  117.                             // (char, char*), returning int
  118.  
  119. char c1 = 'a';                // c1 contains 'a'
  120. char* p = &c1;                // p contains address of c1
  121. char c2 = *p;                // c2 contains 'a'
  122.  
  123. size_t strlen(char* p)
  124. {
  125.     size_t i = 0;
  126.     while(*p++) i++;
  127.     return i;
  128. }
  129.  
  130. // faster pointer string comparison, produces better code in most platforms
  131.  
  132. int strlen(const char* p)
  133. {
  134.     register char *q = p;
  135.     while(*q++)
  136.         return q - p - 1;
  137. }
  138.  
  139.  
  140. // arrays
  141.  
  142. float v[3];                    // array of 3 floats
  143. int   a[3][5];                // 2-dimensional array of ints (3 times 5)
  144. char* vpc[32];                // array of 32 char pointers
  145.  
  146. int v1[1] = {1,  2,  3, 4};    // assigment of array elements
  147.  
  148.  
  149.  
  150. // pointers and arrays
  151.  
  152. char* p = &alpha[0];        // make p point at start of alpha array
  153. char* p = alpha;            // same semantics!
  154.  
  155. extern "C" int strlen(const char*);
  156. void func()
  157. {
  158.     char v[] ="Jeff Steven"
  159.     char* p  = v;
  160.     strlen(p);
  161.     strlen(v);                // both gives same value
  162. }
  163.  
  164.  
  165. // structures
  166.  
  167. struct address {
  168.     char*     name;
  169.     long    number;
  170.     char*    street;
  171.     char*    town;
  172.     char    state[2];
  173.     long    zip;
  174. };
  175.  
  176. address js;
  177. js.name = "Jeff Sandvik";
  178. js.number = 20200;
  179.  
  180.  
  181. address js = {                            // struct assignment
  182.     "Jeff Sandvik",
  183.     20200, "Lucille Ave",
  184.     "Cupertino", {'C','A'}, 95104
  185. };
  186.  
  187.  
  188. void printAddress(address p)            // struct pointer handling
  189. {
  190.     cout     << p->name         << '\n'
  191.             << p->number    << ' '  << p->street << '\n'
  192.             << p->town        << '\n'
  193.             << p->state[0]    << p->state[1]
  194.             << ' '            << p->zip <<'\n'
  195. }
  196.  
  197. address current;
  198.  
  199. address setCurrent(address next)        // address handling
  200. {
  201.     address prev     = current;
  202.     current            = next;
  203.     return prev;
  204. }
  205.  
  206. struct link {                            // struct self referencing
  207.     link*     previous;
  208.     link*    next;
  209. };
  210.  
  211.  
  212.  
  213. // typedef
  214.  
  215. typedef char* Pchar;
  216. Pchar p1, p2;
  217. char  p3 = p1;
  218.  
  219.  
  220. // references (&)  cmp Pascal VAR
  221.  
  222. int  i = 1;                                    // example
  223. int& r = i;
  224. int  x = r;        // x = 1;
  225. r = 2;            // i = 2;
  226.  
  227. void incr(int&a) {a++;}                        // function call
  228.  
  229. void func()
  230. {
  231.     int x = 1;
  232.     incr(x);        // x = 2;
  233. }
  234.  
  235.  
  236. // const
  237.  
  238. const int model = 100;
  239. model = 200;                                // error!
  240.  
  241. const char* pc    = "abc";                    // const pc data
  242. pc[3] ='a';                                    // error!
  243. pc = "def";                                    // ok
  244.  
  245. char* const cp = "abc";                        // constant pointer
  246. cp[3] = 'a';                                // ok
  247. cp = "def";                                    // error!
  248.  
  249. const char *const pc "abc";                    // data and pointer constant
  250.  
  251. char* strcpy(char* p, const char* q);        // can't modify q
  252.  
  253.  
  254. // enums
  255.  
  256. enum {eRed, eBlue, eGreen};                    // enum list, eRed = 0, eBlue = 1...
  257. enum {eRed = 200, eBlue, eGreen = 300};        // eBlue = 201
  258.  
  259. enum eColors {eRed, eBlue, eGreen};            // named enum
  260. eColors returnColor();
  261.  
  262. eColors theColor;
  263.  
  264. switch (theColor){
  265.     case eRed:
  266.         // do something
  267.         break;
  268.     case eBlue:
  269.         // do something
  270.         break;
  271.     case eGreen:
  272.         // do something
  273.         break;
  274.     default:
  275.         // do something
  276.         break;
  277. }
  278.  
  279. class foo{
  280. public:
  281.     enum eColors{
  282.         eRed, eBlue, eGreen};
  283. //...
  284. };
  285.  
  286. myClass.fColor = foo::eRed;
  287.  
  288.  
  289. // bitfields
  290.  
  291. struct ASICReg {
  292.     unsigned enable:     1;        // one bit
  293.     unsigned page:        3;        // three bits
  294.     unsigned :            1;        // unused
  295.     unsigned mode:        2;        // two bits
  296.     unsigned :            4;        // unused
  297.     unsigned access:    1;        // one bit
  298.     unsigned length:    1;
  299.     unsigned non_res:    1;
  300. };
  301.  
  302. ASICReg* SR = (sreg *) 0xA800;    // fictiv address, memory mapped I/O
  303. // ...
  304.  
  305. if (SR->access)    {                // true?
  306.     // clean up the state
  307.     SR->access = 0;
  308. }
  309.  
  310.  
  311. // unions
  312.  
  313. struct entry {
  314.     char*     name;
  315.     char    type;                // tagged value for union
  316.     union {
  317.         char* stringValue;        // char string     type = 's'
  318.         int      intValue;            // or int variable type = 'i'
  319.     };
  320. };
  321.  
  322. union foo {                        // named union
  323.     int     i;
  324.     int*    p;
  325. };
  326.  
  327.  
  328. // modulo
  329.  
  330. const int RANGE = 100;
  331. int i;
  332.  
  333. i %= RANGE;                        // i is in the range 0...RANGE-1
  334.  
  335.  
  336. // left shift
  337.  
  338. int i =0x8000;
  339. i <<= 1;                        // left shift one step
  340.  
  341.  
  342. // bitwise XOR
  343.  
  344. int i = 0x8000;
  345. i ^= 0x3000;                    // note, no space between ^ and =!!!
  346.  
  347. // bitwise OR
  348.  
  349. int i = 0x8000;
  350. i |= 0x3000;
  351.  
  352. // bitwise AND
  353.  
  354. int i = 0x8000;
  355. i &= 0x3000;
  356.  
  357.  
  358. // error stream
  359.  
  360. int numErrors;
  361.  
  362. double error(const char* s)
  363. {
  364.     cerr <<"error: " << s << "\n";
  365.     numErrors++;
  366.     return 1;
  367. }
  368.  
  369.  
  370. // type conversion
  371.  
  372. int foo = 56;
  373. float bar = float(foo);
  374.  
  375. char* p = (char *)0xA800;                // typecast of address
  376. typedef char* Address;
  377. Address p = Address(0xA800);            // same as above
  378.  
  379.  
  380. // free store (new, delete, set_new_handler...)
  381.  
  382. main()                                    // simple example
  383. {
  384.     char *p = saveString("foobar");
  385.     delete[] p;                            // note new 2.0 delete syntax
  386. }
  387.  
  388. char* saveString(const char* p)
  389. {
  390.     char* s = new char[strlen(p) + 1];
  391.     strcpy(s,p);
  392.     return s;
  393. }
  394.  
  395. TFoo *aFoo = new TFoo;                    // create object in the free store (heap on MacOS)
  396.  
  397. #include <stream.h>
  398. #include <new.h>
  399.  
  400. void OutofStore()
  401. {
  402.     cerr << "operator new failed : out of store\n";
  403.     exit(1);
  404. }
  405.  
  406. main()
  407. {
  408.     set_new_handler(&OutOfStore);        // give address to handler
  409.     char* p = new char[100000000000];
  410.     cout <<"what, it works..., address = ", long(p) << '\n';
  411.     // new returns 0 if it can't find enough memory - test for NULL
  412. }
  413.  
  414.  
  415.  
  416. // stack based objects
  417.  
  418. void func()
  419. {
  420.     TFoo aFoo;                            // local -> placed on the stack
  421.     aFoo.Beep();
  422. }                                        // removed from stack automatically
  423.  
  424.  
  425. // ? : conditional expression
  426.  
  427. max = (a <= b) ? b : a;
  428.  
  429.  
  430. // linkage to non-C++ code (no function name mangling
  431.  
  432. #ifdef __cplusplus
  433. extern "C" {
  434. #endif
  435. pascal Handle NewHandle(Size byteCount)
  436. #pragma parameter DisposHandle(__A0)
  437. pascal void DisposHandle(Handle h)
  438.     = 0xA023; 
  439. #ifdef __cplusplus
  440. }
  441. #endif
  442.  
  443. extern "C" {
  444.     char* strcpy(char*, const char*);
  445.     int        strcmp(const char*, const char*);
  446.     // ...
  447. }
  448.  
  449. extern "C" {
  450. #include "myCHeaderFiles.h"
  451. }
  452.  
  453.  
  454. // recursion
  455.  
  456. int fac(int n) {return (n > 1) ? n * fac(n-1) : 1;}
  457.  
  458.  
  459. // overloaded function names
  460.  
  461. void print(int);                // integer print
  462. void print(const char*);        // string print
  463.  
  464.  
  465. // default function arguments
  466.  
  467. void print(int value, int base=10);     
  468. //...
  469. print(30);                        // will use base=10 inside print
  470.  
  471. void foo(int, char*, int = 0, char* = 0);    
  472. // have to define defaults from right!
  473.  
  474.  
  475.  
  476. // unspecified amount of function args
  477.  
  478. int printf(const char ...);
  479.  
  480.  
  481. // pointers to functions
  482.  
  483. void error(char* p) {/* ... */}
  484. void (*efunc)(char*);            // pointer to function
  485.  
  486. void func()
  487. {
  488.     efunc = &error;                // give address to function ptr
  489.     (*efunc)("mayday");            // call the function via ptr
  490. }
  491.  
  492. typedef void (*PF)();
  493.  
  494. PF editOps[] = {                // edit operations
  495.     &cut, &paste, ©
  496. };
  497.  
  498. PF fileOps[] = {
  499.     &new, &save, &close
  500. };
  501.  
  502. PF MenuEntry = editOps;
  503. //...
  504. (*MenuEntry[3])();                // selected copy! trigger copy function
  505.  
  506.  
  507. // macros
  508.  
  509. #define print(a,b)   cout << (a) << (b)        // argument usage
  510. #define forever for(;;)
  511. #define MIN(a,b)   (((a)<(b))?(a):(b))
  512.  
  513.  
  514. // this pointer
  515.  
  516. always defined as X *const this; where X is the name of the class
  517.  
  518. class X{
  519.     int m;
  520. public:
  521.     int readm() {return this->m;}            // makes things more clear!
  522.  
  523.  
  524. class dlink{
  525.     dlink* previous;
  526.     dlink* successor;
  527. public:
  528.     void append(dlink*);
  529. // ...
  530. };
  531.  
  532. void dlink::append(dlink* p )
  533. {
  534.     p->successor = successor;
  535.     p->previous  = this;
  536.     successor->previous = p;
  537.     successor = p;
  538. }
  539.  
  540. dlink* listHead;
  541. void func(dlink* a, dlink* b)
  542. {
  543.     // ...
  544.     listHead->append(a);
  545.     listHead->append(b);
  546. }
  547.  
  548.  
  549. // const member function
  550.  
  551. class X{
  552.     int m;
  553. public:
  554.     readme() const {return m;}            // const member function, read-only
  555.     writeme(int i) {m = i;}
  556. };
  557.  
  558. // you are able to change a value through an explicit this cast:
  559.  
  560. class X{
  561.     int m;
  562. public:
  563.     // ...
  564.     void implicitCheat() const {m++;}                      // error!
  565.     void explicitCheat() const { ((X *)this)->m++;}        // ok
  566. };
  567.  
  568.  
  569. // const classes
  570.  
  571. void func(X& mutable, const X& constant)
  572. {
  573.     mutable.readme();                    // ok
  574.     mutable.writeme(7);                    // ok
  575.     constant.readme();                    // ok
  576.     constant.writeme(7);                // error
  577. }
  578.  
  579.  
  580. // constructors
  581.  
  582. class TDate{
  583.     // ...
  584.     TDate(int day, int month, long year);        // constructor
  585.     TDate(int month, long year);                // other form            
  586.     TDate(long);                                // 910915, ANSI standard
  587.     TDate();                                    // default today's date
  588.     TDate(const char*);                            // string "Sun 15 Sept 1991"
  589.     TDate(int d = 0, int m =0, long year = 0);     // default values
  590. };
  591.  
  592. TDate today(15,9,1991);                            // stack based class
  593. TDate tomorrow("Mon 16 Sept 1991");
  594. TDate now;                                        // today's date
  595. TDate d = today;                                // default copy constructor! bitwise copy
  596.  
  597. TDate::TDate(int d, int m, long y)                // constructor function declaration
  598. {
  599.     // ...
  600. }
  601.  
  602.  
  603. // destructors
  604.  
  605. class TStack{
  606.     int     size;
  607.     char*    top;
  608.     char*    s;
  609. public:
  610.     TStack(int sz) {top = s = new char[size = sz];}
  611.     ~TStack() { delete [] s;}            // destructor
  612.     void push(char c) {*top++ = c;}
  613.     void pop() { return *--top;}
  614. };
  615.  
  616. void func()
  617. {
  618.     TStack s1(100);
  619.     TStack s2(200);
  620.     s1.push('a');
  621.     s2.push('b');
  622.     char ch = s2.pop();
  623.     cout << ch << '\n';
  624. }                                        // automatic call of destructor
  625.  
  626.  
  627.  
  628. // inline calls (see ARM 102 for more info when compiler will not inline
  629.  
  630. class TFoo{
  631. public:
  632.     void func1(){ /*...*/}                // this code is inlined
  633.     void func2();
  634. };
  635.  
  636. inline void 
  637. TFoo::func2()
  638. {                                // this code is inlined
  639. // ...
  640. }
  641.  
  642.  
  643. // friends
  644.  
  645. class x {
  646.     friend class y;                // class y has access to x's private parts
  647.     // ...
  648. };
  649.  
  650. class x{
  651.     friend void y::f();            // y::f() member function has access to
  652.     //...                        // x's private parts
  653. };
  654.  
  655.  
  656. // class member name qualification
  657.  
  658. class X{
  659.     int m;
  660. public:
  661.     int getm() const { return m;}
  662.     void setm(int m) { X::m = m;}    // name qualification
  663. };
  664.  
  665. class TFile(){
  666. // ...
  667.     int open(const char*, const char*);
  668. };
  669.  
  670. int TFile::open(const char* name, const char* spec)
  671. {
  672.     // ...
  673.     if(::open(name,flag)){            // stdclib open called
  674.         // ...
  675.     }
  676.     // ...
  677. }
  678.  
  679.  
  680. // nested classes
  681.  
  682. class TSet {
  683.     struct setmem{                    
  684.         int     mem;
  685.         setmem*    next;
  686.         setmem(int m, setmem* n) {mem = m; next = n;}
  687.     };
  688.     setmem* first;                            // nested class struct
  689. public:
  690.     TSet()     {first = NULL;}
  691.     insert(){first = new setmem(m, first);}
  692.     // ...
  693. };
  694.  
  695.     
  696. // nicer with friends:
  697.  
  698. class TSetmem{
  699. friend class TSet;            // access to members of TSet only
  700.     int     mem;
  701.     setmem*    next;
  702.     setmem(int m, setmem* n) { mem = m, next = n;}
  703.     // other useful members
  704. };
  705.  
  706. class TSet{
  707.     setmem*    first;
  708. public:
  709.     TSet() {first = NULL;}
  710.     insert(int m) {first = new setmem(m, first);}
  711.     // ...
  712. };
  713.  
  714. class X{                    // name scoping 
  715. private:
  716.     struct M1 { int m;}
  717. public:
  718.     struct M2 { int m;}
  719.     M1 f(M2);                // member function
  720. };
  721.  
  722. void func()
  723. {
  724.     M1 a;                    // error, 'M1' not in scope
  725.     M2 b;                    // ok
  726.     X::M1 c;                // error, 'M1' private
  727.     X::M2 d;                // ok
  728. }
  729.  
  730.  
  731. // static class members
  732.  
  733. class TTask{
  734. public:
  735.     // ...
  736.     static TTask* chain;    // static field, one copy of the TTask only
  737.     static void Schedule();    // static member function
  738.     // ...
  739. };
  740.  
  741. TTask* TTask::chain = NULL;
  742. void TTask::Schedule() {/* ....*/};
  743.  
  744. ....
  745. if(TTask::chain == NULL){    // must be qualified by class name
  746.     // do something
  747. }
  748.  
  749. TTask::Schedule();            // call the static member function
  750.  
  751.  
  752. // pointers to members
  753.  
  754. typedef long (TFoo::*Function)();
  755. enum eGenerator{SIMPLE, PRACTICAL, COMPLEX};
  756.  
  757. class TFoo{
  758. private:
  759.    Function fGenerator;       // pointer to Generate function
  760.    int      fVal;
  761. public:
  762.    TFoo(eGenerator);
  763.    long Simple()    { return 2;}
  764.    long Practical()    { return 4;};
  765.    long Complex()    { return 6;}
  766.    long Generate()  { return this->*fGenerator();}    // use the function fGenerator is pointing at
  767. };
  768.  
  769. TFoo::TFoo(eGenerator theGenerator)
  770. {
  771.     switch(theGenerator){                            // set pointer to defined function
  772.         case SIMPLE:
  773.             this->fGenerator = &TFoo:Simple;
  774.             break;
  775.         case PRACTICAL:
  776.             this->fGenerator = &TFoo::Practical;
  777.             break;
  778.         case COMPLEX:
  779.             this->fGenerator = &TFoo:Complex;
  780.     }
  781. }
  782.  
  783.  
  784.  
  785.  
  786.  
  787. // class objects as members
  788.  
  789. class TClassDef{
  790.     table     members;
  791.     int        numMembers;
  792.     // ...
  793.     TClassDef(int size);
  794.     ~TClassDef();
  795. };
  796.  
  797. TClassDef::TClassDef(int size): members(size)    // pass information for init
  798. {
  799.     numMembers = size;
  800.     // ...
  801. }
  802.  
  803.  
  804. // arrays of class objects
  805.  
  806. TTable tbl[10];            // will generate an array of 10 TTable objects
  807.  
  808.  
  809. // new/delete operator overloading
  810.  
  811. class TName {
  812. public:
  813.     char*     string;
  814.     TName*    next;
  815.     double    value;
  816.     
  817.     TName(char*, double name*);
  818.     ~TName();
  819.     
  820.     void* operator new(size_t);
  821.     void  operator delete(void*, size_t);
  822. private:
  823.     enum     {N_ALL = 128};
  824.     static    name* nfree;
  825. };
  826.  
  827. void* TName::operator new(size_t)
  828.     register TName* p = nfree;            // first allocate
  829.     
  830.     if(p)
  831.         nfree = p->next;
  832.     else{
  833.         TName* q = (TName *) new char[N_ALL*sizeof(name)];
  834.         for(p = nfree = &q[N_ALL -1]; q < p; p--)
  835.             p->next = p - 1;
  836.         p->next = NULL;
  837.     }
  838.     return p;
  839. }
  840.  
  841. void TName::operator delete(void* p, size_t)
  842. {
  843.     ((TName *)p)->next = nfree;
  844.     nfree = (TName *)p;
  845. }
  846.  
  847. //....
  848.     *TName::nfree = 0;                    // explicit initialization of the value
  849.     
  850.  
  851.  
  852. // derived classes
  853.  
  854. class TEmployee{
  855. private:
  856.     char*         name;
  857.     short         age;
  858.     short         department;
  859. public:
  860.     TEmployee();
  861.     print() const {/*...*/}
  862.     TEmployee*    next;
  863. }
  864.  
  865. class TManager : public TEmployee{
  866.     TEmployee*    group;
  867.     short        level;
  868. public:
  869.     TManager();
  870.     print() const {/*...*/}
  871. };
  872.  
  873. void TEmployee::print()
  874. {
  875.     cout <<"Employee information...\n";
  876. }
  877.  
  878. void TManager::print()
  879. {
  880.     TEmployee::print();        // print employee information
  881.     cout <<"Manager information...\n";
  882. }
  883.  
  884. void func()
  885. {
  886.     TManager     m1, m2;
  887.     TEmployee     e1, e2;
  888.     TEmployee*    elist;
  889.     
  890.     elist   = &m1;            // put m1 on elist
  891.     m1.next = &e2;            // put e1 on elist
  892.     e1.next = &m2;
  893.     m2.next = &e2;
  894.     e2.next = NULL;            // last in the elist
  895. }
  896.  
  897. void g()
  898. {
  899.     TManager MM;
  900.     Temployee* pe = &MM;    // ok
  901.     
  902.     TEmployee ee;
  903.     manager* PM = ⅇ        // error, not every TEmployee is a TManager
  904.     
  905.     PM->level = 2;            // won't work, no space for level
  906.     
  907.     PM = (TManager *) pe;    // ok
  908.     PM->level = 2;            // ok
  909. }
  910.  
  911.  
  912. // derived constructors/destructors
  913. // class objects are constructed from the bottom up, first the base,
  914. // then the members, then the derived class itself. They are destroyed
  915. // in the opposite order
  916.  
  917. class TEmployee{
  918.     // ...
  919. public:
  920.     TEmployee(char* n, int d);
  921. };
  922.  
  923. class TManager:: public TEmployee{
  924.     // ....
  925. public:
  926.     TManager(char* n, int l, int d);
  927. };
  928.  
  929. TEmployee::TEmployee(char* n, int d)
  930.     :name(n), department(d)
  931. {
  932.     next = list;
  933.     list = this;
  934. }
  935.  
  936. TManager::TManager(char* n, int l, int d)
  937.     :TEmployee(n,d), level(l), group(0)
  938. {
  939.     //...
  940. }
  941.  
  942.  
  943. // class hierarchies
  944.  
  945. class TEmployee { /* .... */ };
  946. class TManager: public TEmployee {/* .... */};
  947. class TDirector: public TManager {'* .... */};
  948. class TTemporary {/* ....*/};
  949.  
  950.  
  951. // multiple inheritance
  952.  
  953. class TConsultant: public TManager, public TTemporary {/* .... */};
  954.  
  955. class TTask{
  956.     //
  957.     virtual info* debug();
  958. };
  959.  
  960. class TDisplayed{
  961.     // ...
  962.     virtual info* debug();
  963. };
  964.  
  965.  
  966. class TSatellite: public TTask, public TDisplayed{
  967.     // ...
  968. };
  969.  
  970. void func(TSatellite& s)            // ambiguity with member function names
  971. {
  972.     s.draw();                        // TDisplayed::draw()
  973.     s.delay(10);                    // TTask::delay(int x);
  974.     s.xmit();                        // TSatellite::Xmit()
  975.     
  976.     info* d_info = s.debug;            // ambiguity problems!
  977.     d_info = s.TTask::debug();        // ok
  978.     d_info = s.TDisplayed::debug()    // ok
  979.     
  980.     // with pointers, TSatellite *s
  981.     d_info = s->TTask::debug();
  982.     d_info = s->TDisplayed::debug();
  983. }
  984.  
  985. // better to define new member functions inside TSatellite!
  986.  
  987. class TSatellite: public TTask, public TDisplayed{
  988.     // ...
  989.     
  990.     info* satelliteDebug()
  991.     {
  992.         info* d1 = TTask::debug();
  993.         info* d2 = TDisplayed::debug();
  994.         return d1.merge(d2);
  995.     }
  996. };
  997.  
  998.  
  999. // virtual functions
  1000.  
  1001. class TEmployee {
  1002.     char*    name;
  1003.     short     department;
  1004.     // ...
  1005.     TEmployee*             next;
  1006.     static TEmployee*    list;
  1007. public:
  1008.     TEmployee(char* n, int d);
  1009.     // ..
  1010.     static void printList();
  1011.     virtual void print() const;                // virtual function, can be
  1012. };                                            // overridden
  1013.  
  1014. ....
  1015. void TEmployee::print() const
  1016. {
  1017.     cout << name << '\t' << department << '\n';
  1018.     // ...
  1019. }
  1020.  
  1021. class TManager::public TEmployee{
  1022.     TEmployee*    group;
  1023.     short        level;
  1024.     // ...
  1025. public:
  1026.     TManager(char* n, int l, int d);
  1027.     // ...
  1028.     void print const();                        // we could override this - virtual
  1029. };
  1030.  
  1031. ....
  1032. void TManager::print() const
  1033. {
  1034.     cout << level << '\n';
  1035.     //...
  1036. }
  1037.  
  1038.  
  1039. // abstract classes
  1040. // pure virtual functions
  1041.  
  1042. class TShape{    // has pure virtual function = abstract class
  1043.     // ...
  1044. public:
  1045.     virtual void rotate(int x) =0;            // pure virtual function
  1046. };
  1047.  
  1048. class TMyShape{
  1049.     // ...
  1050. public:
  1051.     virtual void rotate(int x){/* ... */}    // have to create this member function
  1052. };
  1053.  
  1054. ...
  1055. TShape         aShape;                            // error!
  1056. TMyShape    anotherShape;                    // ok
  1057.  
  1058.  
  1059. // virtual base classes
  1060.  
  1061. class TWindow{
  1062.     // window information
  1063.     void _Draw();                            // internal window draw
  1064.     virtual void Draw(); { _Draw();}        // calls by default _Draw()
  1065. };
  1066.  
  1067. class TWindowBorder : public virtual TWindow{
  1068.     // border information
  1069.     void _Draw();                            // draw border
  1070.     void Draw();
  1071. };
  1072.  
  1073. class TWindowMenu : public virtual TWindow{
  1074.     // menu information
  1075.     void _Draw();                            // draw menu
  1076.     void Draw();
  1077. };
  1078.  
  1079. class TWindowBorderMenu : public virtual TWindow,
  1080.     public TWindowBorder, public TWindowMenu{
  1081.     // ...
  1082.     void _Draw();                            // draw specific stuff
  1083.     void Draw();
  1084. };
  1085.  
  1086. // every class defined virtual base class will be represented by a *single*
  1087. // object of that class.
  1088.  
  1089.     
  1090. void TWindowBorder::Draw()
  1091. {
  1092.     TWindow::Draw();
  1093.     _Draw();                            // draw the border
  1094. }
  1095.  
  1096. void TWindowMenu::Draw()
  1097. {
  1098.     TWindow::Draw();
  1099.     _Draw();                            // draw the menu
  1100. }
  1101.  
  1102. void TWindowBorderMenu::Draw()
  1103. {
  1104.     TWindow::Draw();
  1105.     TWindowBorder::Draw();
  1106.     TWindowMenu::Draw();
  1107.     _Draw();                            // draw specific stuff
  1108. }
  1109.  
  1110.  
  1111. // access control
  1112. // private (class only), protected (shareable by inheritance),
  1113. // public (open)
  1114.  
  1115. class X{
  1116. private:                // no definition = private
  1117.     enum {A, B};
  1118.     void f(int x);
  1119.     int a;
  1120. };
  1121.  
  1122. void X::f(int x)
  1123. {
  1124.     if (x < A) f(x+B);
  1125.     a++;
  1126. }
  1127.  
  1128. void g(X& x)
  1129. {
  1130.     int i = X::A;        // error, X::A is private
  1131.     x.f(2);                // error, X::f() is private
  1132.     x.a++;                // error X::a is private
  1133. }
  1134.  
  1135.  
  1136. // protected members
  1137.  
  1138. class X{
  1139. // private by default
  1140.     int priv;
  1141. protected:
  1142.     int prot;
  1143. public:
  1144.     int publ;
  1145.     void m();
  1146. };
  1147.  
  1148. void X::m()
  1149. {
  1150.     priv = 1;            // ok
  1151.     prot = 2;            // ok
  1152.     publ = 3;            // ok
  1153. }
  1154.  
  1155. class Y : public X{
  1156.     void mDerived();
  1157. };
  1158.  
  1159. void Y::mDerived()
  1160. {
  1161.     priv = 1;            // error, priv is private inside X
  1162.     prot = 2;            // ok, inherited
  1163.     publ = 3;            // ok, public class
  1164. }
  1165.  
  1166. void f(Y* p)
  1167. {
  1168.     p->priv = 1;        // error, priv is private
  1169.     p->prot = 2;        // error, prot is protected, and no inheritance
  1170.     p->publ = 3;        // ok, public class
  1171. }
  1172.  
  1173.  
  1174. // access to base class
  1175.  
  1176. class X{
  1177. public:
  1178.     int a;
  1179.     // ...
  1180. };
  1181.  
  1182. class Y1 : public X { /*...*/}
  1183. class Y2 : protected X {/* ... */}
  1184. class Y3 : private X {/* ... */}      // private default
  1185.  
  1186. void f(Y1* p1,  Y2* p2, Y3* p3)
  1187. {
  1188.     X* q1 = p1;        // ok, X is a public base class of Y1
  1189.     p1->a = 7;        // ok, internal reference to private field
  1190.     q1= p2;            // error, X is a protected base of Y2
  1191.     p2->a = 7;        // error, 
  1192.     q1 = p3;        // error, X is a private base of Y3
  1193.     p3->a = 7;        // error
  1194. }
  1195.  
  1196.  
  1197. // virtual destructors
  1198.  
  1199. class TFoo{
  1200. public:
  1201.     TFoo();                // constructor
  1202.     virtual ~TFoo();    // virtual destructor 
  1203.     // ...
  1204. };
  1205.  
  1206. // this makes it possible for the compiler to keep track of each destructor
  1207. // and the ordering. Most destructors should be virtual!
  1208.  
  1209.  
  1210.  
  1211. // new - placement operator
  1212.  
  1213. class X{
  1214.     // ...
  1215. public:
  1216.     X(int);
  1217. };
  1218.  
  1219. void* operator new(size_t, void* p) {return p;}
  1220.  
  1221. char buffer[sizeof(X)];
  1222.  
  1223. void f(int i)
  1224. {
  1225.     X* p = new(buffer) X(i);    // place X in buffer!
  1226.     // ...
  1227. }
  1228.  
  1229. class TArena{
  1230.     // ...
  1231.     virtual void* alloc(size_t) = 0;
  1232.     virtual void free(void) = 0;
  1233. };
  1234.  
  1235. void* operator new(size_t, sz, Arena* a)
  1236. {
  1237.     return a.alloc(size);
  1238. }
  1239. ...
  1240. extern Arena* Persistent;
  1241. extern Arena* Shared;
  1242.  
  1243. void g(int i)
  1244. {
  1245.     X* p = new(Persistent) X(i);    // X in persistent storage
  1246.     X* q = new(Shared) X(i);        // X in shared memory
  1247.     // ...
  1248. }
  1249.  
  1250. void h(X* p)
  1251. {
  1252.     p->~X();                        // call destructor
  1253.     Persistent->free(p);            // free actual memory
  1254. }
  1255.  
  1256.  
  1257. // operator overloading
  1258.  
  1259. class TComplex{                        // class definition
  1260.     double re, im;
  1261. public:
  1262.     TComplex(double r, double i=0) {re = r, im =i;}
  1263.     friend complex operator+(TComplex, TComplex);
  1264.     friend complex operator*(TComplex, TComplex);
  1265.     
  1266.     TComplex& operator +=(TComplex);
  1267.     TComplex& operator -=(TComplex);
  1268. };
  1269.  
  1270. inline TComplex& TComplex::operator+=(TComplex a)
  1271. {
  1272.     re += a.re;
  1273.     im += a.im;
  1274.     return this;
  1275. }
  1276.  
  1277. inline TComplex operator+(TComplex a, TComplex b)
  1278. {
  1279.     return TComplex(a.re+b.re, a.im + b.im);
  1280. }
  1281.  
  1282.  
  1283. void f()                            // usage
  1284. {
  1285.     complex a = complex(1, 3.1);
  1286.     complex b = complex(1.2, 2);
  1287.     complex c = b;
  1288.     
  1289.     a = b + c;
  1290.     b = b + c * a;
  1291.     c = a * b + complex(1,2);
  1292.     
  1293.     complex d = operator+(a,b);        // explicit call
  1294.     complex e = 23;                    // takes default i value
  1295. }
  1296.  
  1297.  
  1298. // conversion operators
  1299.  
  1300. class TTiny{
  1301.     char     v;
  1302.     void     assign(int i)
  1303.     {
  1304.         if (i>63) {error("range error"); v = i&~63;}
  1305.         v = i;
  1306.     }
  1307. public:
  1308.     TTiny(int i) {assign(i);}
  1309.     TTiny(const TTiny& t) { v = t.v;}
  1310.     TTiny& operator= (const TTiny& t)
  1311.         { v = t.v; return *this;}
  1312.     TTiny& operator=(int i) {assign(i); return *this;}
  1313.     operator int() { return v;}        // conversion operator!
  1314. };
  1315.  
  1316. void main()
  1317. {
  1318.     TTiny c1 = 2;
  1319.     TTiny c2 = 62;
  1320.     TTiny c3 = c2 - c1;                // c3 = 60
  1321.     TTiny c4 = c3;                    // no range check, not necessary
  1322.     int i = c1 + c2;                // i = 64
  1323.     c1 = c2 + 2*c1;                    // c1 = 2
  1324.     c2 = c1 - i;                    // c2 = 2
  1325.     c3 = c2;                        // no range check, not necessary
  1326. }
  1327.  
  1328.  
  1329. // copy constructors
  1330.  
  1331. class TString{
  1332.     char*    p;
  1333.     int     size;                    // of vector pointed to by p
  1334.     
  1335.     TString(int sz) { p = new char[size=sz];}
  1336.     ~TString() { delete [] p;}
  1337.     TString& operator=(const TString&);
  1338.     TString(const TString&);        // copy constructor!
  1339. };
  1340.  
  1341. TString::TString(const TString& a)  // (if not defined, bitwise copy generated by compiler
  1342. {
  1343.     p = new char[size =a.size];
  1344.     strcpy(p, a.p);
  1345. }
  1346.  
  1347. TString& TString::operator=(const TString& a)
  1348. {
  1349.     if(this != &a){
  1350.         delete [] p;
  1351.         p = new char[size = a.size];
  1352.         strcpy(p, a.p);
  1353.     }
  1354.     return *this;
  1355. }
  1356.  
  1357. void f()
  1358. {
  1359.     TString s1(10);
  1360.     TString s2 = s1;    // initialization, not assignment
  1361. }
  1362.  
  1363. // memberwise initalization
  1364.  
  1365. class TString{
  1366. public:
  1367.     TString(const TString& s)
  1368. //
  1369. private:
  1370.     short     len;
  1371.     char    str[255];
  1372. };
  1373.  
  1374. TString(const TString&)
  1375. {
  1376.     this->len = s.len;
  1377.     this->str = s.str;
  1378. }
  1379.  
  1380. //...
  1381.     TString foo = bar;
  1382.  
  1383.  
  1384. // subscripting  - operator [] overload
  1385.  
  1386. #include <string.h>
  1387.  
  1388. class TAssoc{
  1389.     struct pair{
  1390.         char*     name;
  1391.         int        val;
  1392.     };
  1393.     pair*    vector;
  1394.     int     max;
  1395.     int     nfree;
  1396.     
  1397.     TAssoc(const& TAssoc&);                // prevent copying
  1398.     TAssoc& operator=(const TAssoc&);    // prevent assignment
  1399. public:
  1400.     TAssoc(int);
  1401.     int& operator[](const char*);        // operator [] overload
  1402.     void PrintAll();
  1403. };
  1404.  
  1405. TAssoc::TAssoc(int s)
  1406. {
  1407.     max = (s < 16) ? s : 16;
  1408.     nfree = 0;
  1409.     vector = new pair[max];
  1410. }
  1411.  
  1412. int& TAssoc::operator[](const char* p)
  1413. // maintain a set of pairs, search for p, return a reference to the
  1414. // integer part of its "pair",, make a new "pair" if "p" has not been seen
  1415.  
  1416.     register pair* pp;
  1417.     
  1418.     for(pp = vector + free - 1 ; vector <= pp; pp--)
  1419.         if( strcmp(p,pp->name) == 0 ) return pp->val;
  1420.     
  1421.     if(nfree == max){        // overflow, grow the vector
  1422.         pair* newvec = new pair[max*2];
  1423.         for(int i=0; i < max; i++)
  1424.             newvec[i] = vector[i];
  1425.         delete [] vector;
  1426.         vector = newvector;
  1427.         max = 2*max;
  1428.     }
  1429.     
  1430.     pp = &vector[nfree++];
  1431.     pp->name = new char[strlen(p) + 1];
  1432.     strcpy(pp->name, p);
  1433.     pp->val = 0;            // initial value
  1434.     return pp->val;
  1435. }
  1436.  
  1437. void TAssoc::PrintAll()
  1438. {
  1439.     for(int i=0; i <nfree; i++)
  1440.         cout <<vector[i].name << ": " << vector[i].val << "\n";
  1441. }
  1442.  
  1443. main()
  1444. {
  1445.     const MAX = 256;
  1446.     char buf[MAX];
  1447.     
  1448.     TAssoc aVector(512);
  1449.     while (cin >>buf) aVector[buf]++;
  1450.     aVector.PrintAll();
  1451. }
  1452.  
  1453.  
  1454. // function call overload
  1455.  
  1456. class TAssoc{
  1457.     friend class TAssocIterator;
  1458.     pair*     vec;
  1459.     int     max;
  1460.     int        free;
  1461. public:
  1462.     TAssoc(int);
  1463.     int& operator[](const char*);
  1464. };
  1465.  
  1466. class TAssocIterator{
  1467.     TAssoc* cs;                // current TAssoc array
  1468.     int        i;                // current index
  1469. public:
  1470.     TAssocIterator(const TAssoc& s) {cs = &s; i = 0;}
  1471.     pair* operator()()        // function call operator overload
  1472.     {    return (i < cs->free) ? &cs->vec[i++] : NULL;}
  1473. };
  1474.  
  1475. main()    // count the occurrences of each word on input
  1476. {
  1477.     const MAX = 256;
  1478.     char buf[MAX];
  1479.     TAssoc aVector(256);
  1480.     
  1481.     while(cin>>buf) aVector[buf]++;
  1482.     TAssocIterator next(aVector);
  1483.     pair* p;
  1484.     
  1485.     while(p = next())
  1486.         cout <<p->name << ": " << p->val << '\n';
  1487. }
  1488.  
  1489.  
  1490. // dereferencing operator ->
  1491.  
  1492. class TPtr{
  1493.     // ...
  1494.     X* operator->();    // class X
  1495. };
  1496.  
  1497. void f(TPtr p)            // usage
  1498. {
  1499.     p->m = 7;            // (p.operator->())->m =  7;
  1500. }
  1501.  
  1502. // smart pointers
  1503.  
  1504. class TRecPtr{
  1505.     Rec* inCoreAddress;
  1506.     const char* ID;
  1507.     // ...
  1508. public:
  1509.     TRecPtr(const char* p)
  1510.         : identifier(p) {inCoreAddress = NULL;}
  1511.     ~TRecPtr()
  1512.         { WriteToDisk(inCoreAddress, ID);}
  1513.     Rec* operator->();
  1514. };
  1515.  
  1516. Rec* TRecPtr::operator->()
  1517. {
  1518.     if(inCoreAddress == NULL)
  1519.         inCoreAddress = ReadFromDisk(ID);
  1520.     return inCoreAddress;
  1521. }
  1522.  
  1523. main(int argc, const char* argv)        // usage
  1524. {
  1525.     for(int i = argc; i; i--){
  1526.         TRecPtr p(argv[i]);
  1527.         p->update();
  1528.     }
  1529. }
  1530.  
  1531.  
  1532. // increment/decrement operator overloading
  1533.  
  1534. class TCheckedPtrToT{
  1535.     T*    p;
  1536.     T*     array;
  1537.     int    size;
  1538. public:
  1539.     // bind to array 'a' of size 's' initial value 'p'
  1540.     TCheckedPtrToT(T* p, T* a, int s);
  1541.     
  1542.     // bind to single objec initial value 'p'
  1543.     TCheckedPtrToT(T* p);
  1544.     
  1545.     T* operator++();                // prefix
  1546.     T* operator++(int);                // postfix - works from Cfront 3.0 forward
  1547.     
  1548.     T* operator--();                // prefix
  1549.     T* operator--(int);                // postfix - works from Cfront 3.0 forward
  1550.     
  1551.     T& operator*();                    // prefix
  1552. };
  1553.  
  1554. void func(T a)                        // example of use
  1555. {
  1556.     T v[200];
  1557.     TCheckedPtrToT p(&v[0],v,200);    // create object
  1558.     p.operator--(1);
  1559.     p.operator*() = a;                // runtime error, 'p' out of range
  1560.     p.operator++();
  1561.     p.operator*() = a;                // ok
  1562. }
  1563.  
  1564.  
  1565. // string class implementation
  1566.  
  1567. #include <iostream.h>
  1568. #include <string.h>
  1569.  
  1570. class TString{
  1571.     struct srep{
  1572.         char*    s;                    // pointer to data
  1573.         int     n;                    // reference count
  1574.         srep() { n  =1;}
  1575.     };
  1576.     srep* p;
  1577.  
  1578. public:
  1579.     TString(const char*);            // TString x = "abc";
  1580.     TString();                        // TString x;
  1581.     TString(const TString&);        // TString x = TString ...
  1582.     TString& operator=(const char*);
  1583.     TString& operator=(const TString&);
  1584.     ~TString();
  1585.     char&    operator[](int i);
  1586.     
  1587.     friend ostream& operator<<(ostream&, const TString&);
  1588.     friend istream& operator>>(istream&, TString&);
  1589.     
  1590.     friend int operator==(const TString &x, const char *s)
  1591.         { return strcmp(x.p->s, s) == 0;}
  1592.         
  1593.     friend int operator==(const TString &x, const TString &y)
  1594.         { return strcmp(x.p->s, y.p->s) == 0;}
  1595.     
  1596.     friend int operator !=(const TString &x, const char *s)
  1597.         { return strcmp(x.p->s, s) != 0;}
  1598.     
  1599.     friend int operator !=(const TString &x, const Tstring &y)
  1600.         { return strcmp(x.p->s, y.p->s) != 0;}
  1601. };
  1602.  
  1603. TString::TString()                        // constructor
  1604. {
  1605.     p = new srep;
  1606.     p->s = NULL;
  1607. }
  1608.  
  1609. TString::TString(const TString& x)        // copy constructor
  1610. {
  1611.     x.p->n++;
  1612.     p = x.p;
  1613. }
  1614.  
  1615. TString::TString(const char* s)
  1616. {
  1617.     p = new srep;
  1618.     p->s = new char[strlen(s) + 1];
  1619.     strcpy(p->s, s);
  1620. }
  1621.  
  1622. TString::~TString()
  1623. {
  1624.     if(--p->n == 0){
  1625.         delete [] p->s;
  1626.         delete p;
  1627.     }
  1628. }
  1629.  
  1630.  
  1631. TString& TString::operator=(const char *s)
  1632. {
  1633.     if(p->n > 1){                        // disconnect self
  1634.         p->n--;
  1635.         p = new srep;
  1636.     }
  1637.     else                                // free old string
  1638.         delete[] p->s;
  1639.         
  1640.     p->s = new char[strlen(s) + 1];
  1641.     strcpy(p->s, s);
  1642.     return *this;
  1643. }
  1644.  
  1645.  
  1646. TString& TString::operator=(const TString& x)
  1647. {
  1648.     x.p->n++;                            // protect against 'st = st'
  1649.     if(--p->n == 0){
  1650.         delete[] p-s;
  1651.         delete p;
  1652.     }
  1653.     p = x.p;
  1654.     return *this;
  1655. }
  1656.  
  1657.  
  1658. ostream& operator<<(ostream& s, const TString& x)
  1659. {
  1660.     return s << x.p->s << " [" << x.p->n <<"]\n";
  1661. }
  1662.  
  1663.  
  1664. istream& operator>>(istream& s, TString& x)
  1665. {
  1666.     char buf[256];
  1667.     s.get(buf,256);
  1668.     char c;
  1669.     if(s.get(c) && c != '\n'){
  1670.         // buffer overflow, line longer than buffer
  1671.     }
  1672.     
  1673.     x = buf;
  1674.     cout << "echo: " << x <<'\n';
  1675.     return s;
  1676. }
  1677.  
  1678.  
  1679. void error(const char* p)
  1680. {
  1681.     cerr << p << '\n';
  1682.     exit(1);
  1683. }
  1684.  
  1685.  
  1686. char& TString::operator[](int i)
  1687. {
  1688.     if (i<0 || strlen(p->s) < i) error ("index out of range");
  1689.     return p->s[i];
  1690. }
  1691.  
  1692.  
  1693. int main()                            // example of usage
  1694. {
  1695.     TString x[100];
  1696.     
  1697.     cout <<"here we go!\n";
  1698.     
  1699.     for(int n = 0; cin >x[n]; n++){
  1700.         if(n == 100){
  1701.             error("too many strings");
  1702.             return 99;
  1703.         }
  1704.         
  1705.         TString y;
  1706.         cout << (y = x[n]);
  1707.         if(y == "done") break;
  1708.     }
  1709.     
  1710.     cout  << "here we go back again!\n";
  1711.     for(int i = n-1; 0<=i; i--) cout << x[i];
  1712.     
  1713.     return 0;
  1714. }
  1715.  
  1716.  
  1717. // casting of class
  1718.  
  1719. class TBase { ... } b;
  1720. class Tdpriv : private TBase { ... } dv;
  1721. class Tdpub  : public  TBase { ... } db;
  1722. foo(TBase b) { ... }
  1723.  
  1724. foo(b);            // legal
  1725. foo(db);        // legal
  1726. foo(dv);        // NOT legal!!
  1727. foo((TBase)dv);    // legal
  1728.  
  1729.  
  1730. // access control - adjustment
  1731.  
  1732. class TBase{
  1733. public:
  1734.     virtual void func(void){};
  1735. };
  1736.  
  1737. class derived1 : private TBase{
  1738. public:
  1739.     TBase::func;
  1740. };
  1741.  
  1742. class derived2 : private derived1{
  1743. public:
  1744.     void func(void){};
  1745. };
  1746.  
  1747. main()
  1748. {
  1749.     derived2* foo = new derived2;    
  1750.     return 0;
  1751. }
  1752.  
  1753.  
  1754. // more esoteric tricks
  1755.  
  1756.  
  1757. // passing variable arguments to constructor
  1758.  
  1759. #include <stdarg.h>
  1760.  
  1761. class TBase {  ... TBase(int); Init(va_list); ... };
  1762.  
  1763. class TDerived : public TBase { ... TDerived(int, ...); ... };
  1764.  
  1765. TDerived::TDerived(int i, ... ) : TBase(i) {
  1766.     va_list ap;
  1767.     va_start(ap, i);
  1768.     Init(ap);
  1769.     va_end(ap);
  1770. }
  1771.  
  1772.  
  1773.  
  1774.  
  1775.  
  1776.         
  1777.  
  1778.  
  1779.         
  1780.  
  1781.     
  1782.